package cn.bugstack.binding;

import cn.bugstack.session.SqlSession;
import cn.bugstack.util.ClassScanner;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 映射器注册机
 */
public class MapperRegistry {

    /**
     *  目的是将已经添加的映射器假如到HashMap中，方便后续使用
     *
     *  所以这个代码有两个方法 即getMapper addMapper （有两种方式）
     */

     /**
      * 核心组件
      */

    private final Map<Class<?>,MapperProxyFactory<?>> knownMappers = new HashMap<>();

    /*
    * 这个方法主要用来添加映射器
    * */
    public <T> T getMapper(Class<T> type,SqlSession sqlSession){
        //  得到映射器工厂
        final MapperProxyFactory<T> mapperProxyFactory = new MapperProxyFactory<>(type);

        if(mapperProxyFactory == null){
            throw new RuntimeException("Type " + type + " is not known to the MapperRegistry");
        }

        try{
            return mapperProxyFactory.newInstance(sqlSession);
        }catch (Exception e){
            throw new RuntimeException("Error getting mapper instance. Cause: " + e, e);
        }
    }

    public <T> void addMapper(Class<T> type){
        /**
         *  Mapper 必须是接口才会注册
         */
//        先看mapper是不是接口
        if(type.isInterface()){
            if(hasMapper(type)){
                // 如果重复添加了，报错
                throw new RuntimeException("Type " + type + " is already known to the MapperRegistry.");
            }
        }
    }

    public void addMappers(String packageName){
        Set<Class<?>>  mapperSet = ClassScanner.scanPackage(packageName);
        for (Class<?> mapper : mapperSet) {
            addMapper(mapper);
        }
    }

    // 在 MapperRegistry.java 中添加
    private <T> boolean hasMapper(Class<T> type) {
        return knownMappers.containsKey(type);
    }
}
